home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / NORMAL.C < prev    next >
Text File  |  1991-10-02  |  34KB  |  947 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <conio.h>
  7. #include <dos.h>
  8. #include "dflat.h"
  9.  
  10. #ifdef INCLUDE_MULTIDOCS
  11. static void near PaintOverLappers(WINDOW wnd);
  12. static void near PaintUnderLappers(WINDOW wnd);
  13. #endif
  14. static int InsideWindow(WINDOW, int, int);
  15. #ifdef INCLUDE_SYSTEM_MENUS
  16. static void TerminateMoveSize(void);
  17. static void SaveBorder(RECT);
  18. static void RestoreBorder(RECT);
  19. static RECT PositionIcon(WINDOW);
  20. static void near dragborder(WINDOW, int, int);
  21. static void near sizeborder(WINDOW, int, int);
  22. static int px = -1, py = -1;
  23. static int diff;
  24. static int conditioning;
  25. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc,
  26.                                 {-1,-1,-1,-1}};
  27. static int *Bsave;
  28. static int Bht, Bwd;
  29. int WindowMoving;
  30. int WindowSizing;
  31. #endif
  32. /* -------- array of class definitions -------- */
  33. CLASSDEFS classdefs[] = {
  34.     #undef ClassDef
  35.     #define ClassDef(c,b,p,a) {b,p,a},
  36.     #include "classes.h"
  37. };
  38. WINDOW HiddenWindow;
  39.  
  40. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  41. {
  42.     int mx = (int) p1 - GetLeft(wnd);
  43.     int my = (int) p2 - GetTop(wnd);
  44.     int DoneClosing = FALSE;
  45.     switch (msg)    {
  46.         case CREATE_WINDOW:
  47.             AppendBuiltWindow(wnd);  /* add to the lists */
  48.             AppendFocusWindow(wnd);
  49. #ifdef INCLUDE_SCROLLBARS
  50.             if (!SendMessage(NULLWND, MOUSE_INSTALLED, 0, 0))
  51.                 ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  52. #endif
  53.             if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  54.                 GetVideoBuffer(wnd);
  55.             break;
  56.         case SHOW_WINDOW:
  57.             if ((GetParent(wnd) == NULLWND ||
  58.                         isVisible(GetParent(wnd)))
  59. #ifdef INCLUDE_SYSTEM_MENUS
  60.                             && !conditioning
  61. #endif
  62.                                                     )    {
  63.                 WINDOW cwnd = Focus.FirstWindow;
  64.                 if (TestAttribute(wnd, SAVESELF) &&
  65.                                 wnd->videosave == NULL)
  66.                     GetVideoBuffer(wnd);
  67.                 SetVisible(wnd);
  68.                 SendMessage(wnd, PAINT, 0, 0);
  69.                 SendMessage(wnd, BORDER, 0, 0);
  70.                 /* --- show the children of this window --- */
  71.                 while (cwnd != NULLWND)    {
  72.                     if (GetParent(cwnd) == wnd &&
  73.                             cwnd->condition != ISCLOSING)
  74.                         SendMessage(cwnd, msg, p1, p2);
  75.                     cwnd = NextWindow(cwnd);
  76.                 }
  77.             }
  78.             break;
  79.         case HIDE_WINDOW:
  80.             if (isVisible(wnd)
  81. #ifdef INCLUDE_SYSTEM_MENUS
  82.                 && !conditioning
  83. #endif
  84.                                 )    {
  85.                 WINDOW cwnd = Focus.LastWindow;
  86.                 /* --- hide the children of this window --- */
  87.                 while (cwnd != NULLWND)    {
  88.                     if (GetParent(cwnd) == wnd)
  89.                         ClearVisible(cwnd);
  90.                     cwnd = PrevWindow(cwnd);
  91.                 }
  92.                 /* --- paint what this window covered --- */
  93.                 if (wnd->videosave != NULL)
  94.                     RestoreVideoBuffer(wnd);
  95. #ifdef INCLUDE_MULTIDOCS
  96.                 else if (isVisible(GetParent(wnd)))
  97.                     PaintOverLappers(wnd);
  98. #endif
  99.                 ClearVisible(wnd);
  100.             }
  101.             break;
  102. #ifdef INCLUDE_HELP
  103.         case DISPLAY_HELP:
  104.             DisplayHelp(wnd, (char *)p1);
  105.             break;
  106. #endif
  107.         case INSIDE_WINDOW:
  108.             return InsideWindow(wnd, (int) p1, (int) p2);
  109.         case KEYBOARD:
  110. #ifdef INCLUDE_HELP
  111.             if ((int)p1 == F1)    {
  112. #ifdef INCLUDE_SYSTEM_MENUS
  113.                 if (WindowMoving || WindowSizing)
  114.                     break;
  115. #endif
  116.                 SendMessage(wnd, COMMAND, ID_HELP, 0);
  117.                 break;
  118.             }
  119. #endif
  120. #ifdef INCLUDE_SYSTEM_MENUS
  121.             if (WindowMoving || WindowSizing)    {
  122.                 /* -- move or size a window with keyboard -- */
  123.                 int x, y;
  124.                 x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  125.                 y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  126.                 switch ((int)p1)    {
  127.                     case ESC:
  128.                         TerminateMoveSize();
  129.                         return TRUE;
  130.                     case UP:
  131.                         if (y)
  132.                             --y;
  133.                         break;
  134.                     case DN:
  135.                         if (y < SCREENHEIGHT-1)
  136.                             y++;
  137.                         break;
  138.                     case FWD:
  139.                         if (x < SCREENWIDTH-1)
  140.                             x++;
  141.                         break;
  142.                     case BS:
  143.                         if (x)
  144.                             --x;
  145.                         break;
  146.                     case '\r':
  147.                         SendMessage(wnd,BUTTON_RELEASED,x,y);
  148.                     default:
  149.                         return TRUE;
  150.                 }
  151.                 /* -- use the mouse functions to move/size - */
  152.                 SendMessage(wnd, MOUSE_CURSOR, x, y);
  153.                 SendMessage(wnd, MOUSE_MOVED, x, y);
  154.                 break;
  155.             }
  156. #endif
  157.         /* --- unprocessed keystrokes fall through here --- */
  158.         case ADDSTATUS:
  159.         case SHIFT_CHANGED:
  160.             PostMessage(GetParent(wnd), msg, p1, p2);
  161.             break;
  162.         case PAINT:
  163.             if (isVisible(wnd))    
  164.                 ClearWindow(wnd, (RECT *)p1, ' ');
  165.             break;
  166.         case BORDER:
  167.             if (isVisible(wnd))    {
  168.                 if (TestAttribute(wnd, HASBORDER))
  169.                     RepaintBorder(wnd, (RECT *)p1);
  170.                 else if (TestAttribute(wnd, HASTITLEBAR))
  171.                     DisplayTitle(wnd, (RECT *)p1);
  172.                 if (wnd->StatusBar != NULLWND)
  173.                     SendMessage(wnd->StatusBar, PAINT, p1, 0);
  174.             }
  175.             break;
  176. #ifdef INCLUDE_SYSTEM_MENUS
  177.         case COMMAND:
  178.             switch ((int)p1)    {
  179. #ifdef INCLUDE_HELP
  180.                 case ID_HELP:
  181.                     DisplayHelp(wnd, ClassNames[GetClass(wnd)]);
  182.                     break;
  183. #endif
  184.                 case ID_SYSRESTORE:
  185.                     SendMessage(wnd, RESTORE, 0, 0);
  186.                     break;
  187.                 case ID_SYSMOVE:
  188.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  189.                         (PARAM) &dwnd);
  190.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  191.                         (PARAM) &dwnd);
  192.                     SendMessage(wnd, MOUSE_CURSOR,
  193.                         GetLeft(wnd), GetTop(wnd));
  194.                     WindowMoving = TRUE;
  195.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  196.                     break;
  197.                 case ID_SYSSIZE:
  198.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  199.                         (PARAM) &dwnd);
  200.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  201.                         (PARAM) &dwnd);
  202.                     SendMessage(wnd, MOUSE_CURSOR,
  203.                         GetRight(wnd), GetBottom(wnd));
  204.                     WindowSizing = TRUE;
  205.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  206.                     break;
  207.                 case ID_SYSMINIMIZE:
  208.                     SendMessage(wnd, MINIMIZE, 0, 0);
  209.                     break;
  210.                 case ID_SYSMAXIMIZE:
  211.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  212.                     break;
  213.                 case ID_SYSCLOSE:
  214.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  215.                     break;
  216.                 default:
  217.                     break;
  218.             }
  219.             break;
  220. #endif
  221.         case SETFOCUS:
  222.             if (p1 && inFocus != wnd)    {
  223.                 WINDOW pwnd = GetParent(wnd);
  224.                    int Redraw = isVisible(wnd) &&
  225.                        !TestAttribute(wnd, SAVESELF);
  226.                 if (GetClass(pwnd) == APPLICATION)    {
  227.                     WINDOW cwnd = Focus.FirstWindow;
  228.                     /* -- if no children, do not need selective
  229.                         redraw --- */
  230.                     while (cwnd != NULLWND)    {
  231.                         if (GetParent(cwnd) == wnd)
  232.                             break;
  233.                         cwnd = NextWindow(cwnd);
  234.                     }
  235.                     if (cwnd == NULLWND)
  236.                         Redraw = FALSE;
  237.                 }
  238.                 /* ---- setting focus ------ */
  239.                 SendMessage(inFocus, SETFOCUS, FALSE, 0);
  240.  
  241.                 if (Redraw)
  242.                     PaintUnderLappers(wnd);
  243.  
  244.                 /* remove window from list */
  245.                 RemoveFocusWindow(wnd);
  246.                 /* move window to end of list */
  247.                 AppendFocusWindow(wnd);
  248.                 inFocus = wnd;
  249.  
  250.                 if (Redraw)
  251.                     SendMessage(wnd, BORDER, 0, 0);
  252.                 else    {
  253.                     if (pwnd == NULLWND ||
  254.                         GetClass(pwnd) == DIALOG ||
  255.                             DerivedClass(GetClass(pwnd)) ==
  256.                                 DIALOG || GetClass(pwnd) ==
  257.                                         APPLICATION)
  258.                         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  259.                     else
  260.                         SendMessage(pwnd, SHOW_WINDOW, 0, 0);
  261.                 }
  262.             }
  263.             else if (!p1 && inFocus == wnd)    {
  264.                 /* -------- clearing focus --------- */
  265.                 inFocus = NULL;
  266.                 SendMessage(wnd, BORDER, 0, 0);
  267.             }
  268.             break;
  269.         case DOUBLE_CLICK:
  270.             if (!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  271.                         CaptureMouse == NULLWND)    {
  272.                 PostMessage(GetParent(wnd), msg, p1, p2);
  273.                 break;
  274.             }
  275. #ifdef INCLUDE_SYSTEM_MENUS
  276.             if (!WindowSizing && !WindowMoving)
  277. #endif
  278.                 if (HitControlBox(wnd, mx, my))
  279.                     PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  280.             break;
  281.         case LEFT_BUTTON:
  282. #ifdef INCLUDE_SYSTEM_MENUS
  283.             if (WindowSizing || WindowMoving)
  284.                 return FALSE;
  285. #endif
  286.             if ((!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  287.                     CaptureMouse == NULLWND) ||
  288.                         HitControlBox(wnd, mx, my))    {
  289.                 PostMessage(GetParent(wnd), msg, p1, p2);
  290.                 break;
  291.             }
  292. #ifdef INCLUDE_SYSTEM_MENUS
  293.             if (my == 0 && mx > -1 && mx < WindowWidth(wnd))   {
  294.                 /* ---------- hit the top border -------- */
  295.                 if (TestAttribute(wnd, MINMAXBOX) &&
  296.                         TestAttribute(wnd, HASTITLEBAR))  {
  297.                     if (mx == WindowWidth(wnd)-2)    {
  298.                         if (wnd->condition == ISRESTORED)
  299.                             /* --- hit the maximize box --- */
  300.                             SendMessage(wnd, MAXIMIZE, 0, 0);
  301.                         else
  302.                             /* --- hit the restore box --- */
  303.                             SendMessage(wnd, RESTORE, 0, 0);
  304.                         break;
  305.                     }
  306.                     if (mx == WindowWidth(wnd)-3)    {
  307.                         /* --- hit the minimize box --- */
  308.                         if (wnd->condition != ISMINIMIZED)
  309.                             SendMessage(wnd, MINIMIZE, 0, 0);
  310.                         break;
  311.                     }
  312.                 }
  313.                 if (wnd->condition != ISMAXIMIZED &&
  314.                             TestAttribute(wnd, MOVEABLE))    {
  315.                     WindowMoving = TRUE;
  316.                     px = mx;
  317.                     py = my;
  318.                     diff = (int) mx;
  319.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  320.                         (PARAM) &dwnd);
  321.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  322.                 }
  323.                 break;
  324.             }
  325.             if (mx == WindowWidth(wnd)-1 &&
  326.                     my == WindowHeight(wnd)-1)    {
  327.                 /* ------- hit the resize corner ------- */
  328.                 if (wnd->condition == ISMINIMIZED ||
  329.                         !TestAttribute(wnd, SIZEABLE))
  330.                     break;
  331.                 if (wnd->condition == ISMAXIMIZED)    {
  332.                     if (TestAttribute(GetParent(wnd),HASBORDER))
  333.                         break;
  334.                     /* ----- resizing a maximized window over a
  335.                             borderless parent ----- */
  336.                     wnd = GetParent(wnd);
  337.                 }
  338.                 WindowSizing = TRUE;
  339.                 SendMessage(wnd, CAPTURE_MOUSE,
  340.                     TRUE, (PARAM) &dwnd);
  341.                 dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  342.             }
  343. #endif
  344.             break;
  345. #ifdef INCLUDE_SYSTEM_MENUS
  346.         case MOUSE_MOVED:
  347.             if (WindowMoving)    {
  348.                 int leftmost = 0, topmost = 0,
  349.                     bottommost = SCREENHEIGHT-2,
  350.                     rightmost = SCREENWIDTH-2;
  351.                 int x = (int) p1 - diff;
  352.                 int y = (int) p2;
  353.                 if (GetParent(wnd) != NULLWND &&
  354.                         !TestAttribute(wnd, NOCLIP))    {
  355.                     WINDOW wnd1 = GetParent(wnd);
  356.                     topmost    = GetClientTop(wnd1);
  357.                     leftmost   = GetClientLeft(wnd1);
  358.                     bottommost = GetClientBottom(wnd1);
  359.                     rightmost  = GetClientRight(wnd1);
  360.                 }
  361.                 if (x < leftmost || x > rightmost ||
  362.                         y < topmost || y > bottommost)    {
  363.                     x = max(x, leftmost);
  364.                     x = min(x, rightmost);
  365.                     y = max(y, topmost);
  366.                     y = min(y, bottommost);
  367.                     SendMessage(NULLWND,MOUSE_CURSOR,x+diff,y);
  368.                 }
  369.                 if (x != px || y != py)    {
  370.                     px = x;
  371.                     py = y;
  372.                     dragborder(wnd, x, y);
  373.                 }
  374.                 return TRUE;
  375.             }
  376.             if (WindowSizing)    {
  377.                 sizeborder(wnd, (int) p1, (int) p2);
  378.                 return TRUE;
  379.             }
  380.             break;
  381.         case BUTTON_RELEASED:
  382.             if (WindowMoving || WindowSizing)    {
  383.                 if (WindowMoving)
  384.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  385.                 else
  386.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  387.                 TerminateMoveSize();
  388.             }
  389.             break;
  390.         case MAXIMIZE:
  391.             if (wnd->condition != ISMAXIMIZED)    {
  392.                 RECT rc = {0, 0, 0, 0};
  393.                 RECT holdrc;
  394.                 holdrc = wnd->RestoredRC;
  395.                 rc.rt = SCREENWIDTH-1;
  396.                 rc.bt = SCREENHEIGHT-1;
  397.                 if (GetParent(wnd))
  398.                     rc = ClientRect(GetParent(wnd));
  399.                 wnd->condition = ISMAXIMIZED;
  400.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  401.                 conditioning = TRUE;
  402.                 SendMessage(wnd, MOVE,
  403.                     RectLeft(rc), RectTop(rc));
  404.                 SendMessage(wnd, SIZE,
  405.                     RectRight(rc), RectBottom(rc));
  406.                 conditioning = FALSE;
  407.                 if (wnd->restored_attrib == 0)
  408.                     wnd->restored_attrib = wnd->attrib;
  409. #ifdef INCLUDE_SHADOWS
  410.                 ClearAttribute(wnd,    SHADOW);
  411. #endif
  412.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  413.                 wnd->RestoredRC = holdrc;
  414.             }
  415.             break;
  416.         case MINIMIZE:
  417.             if (wnd->condition != ISMINIMIZED)    {
  418.                 RECT rc;
  419.                 RECT holdrc;
  420.  
  421.                 holdrc = wnd->RestoredRC;
  422.                 rc = PositionIcon(wnd);
  423.                 wnd->condition = ISMINIMIZED;
  424.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  425.                 conditioning = TRUE;
  426.                 SendMessage(wnd, MOVE,
  427.                     RectLeft(rc), RectTop(rc));
  428.                 SendMessage(wnd, SIZE,
  429.                     RectRight(rc), RectBottom(rc));
  430.                 SetPrevFocus(wnd);
  431.                 conditioning = FALSE;
  432.                 if (wnd->restored_attrib == 0)
  433.                     wnd->restored_attrib = wnd->attrib;
  434.                 ClearAttribute(wnd,
  435.                     SHADOW | SIZEABLE | HASMENUBAR |
  436.                     VSCROLLBAR | HSCROLLBAR);
  437.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  438.                 wnd->RestoredRC = holdrc;
  439.             }
  440.             break;
  441.         case RESTORE:
  442.             if (wnd->condition != ISRESTORED)    {
  443.                 RECT holdrc;
  444.                 holdrc = wnd->RestoredRC;
  445.                 wnd->condition = ISRESTORED;
  446.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  447.                 wnd->attrib = wnd->restored_attrib;
  448.                 wnd->restored_attrib = 0;
  449.                 conditioning = TRUE;
  450.                 SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  451.                     wnd->RestoredRC.tp);
  452.                 wnd->RestoredRC = holdrc;
  453.                 SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  454.                     wnd->RestoredRC.bt);
  455.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  456.                 conditioning = FALSE;
  457.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  458.             }
  459.             break;
  460.         case MOVE:    {
  461.             WINDOW wnd1 = Focus.FirstWindow;
  462.             int wasVisible = isVisible(wnd);
  463.             int xdif = (int) p1 - wnd->rc.lf;
  464.             int ydif = (int) p2 - wnd->rc.tp;
  465.  
  466.             if (xdif == 0 && ydif == 0)
  467.                 return FALSE;
  468.             if (wasVisible)
  469.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  470.             wnd->rc.lf = (int) p1;
  471.             wnd->rc.tp = (int) p2;
  472.             wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  473.             wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  474.             if (wnd->condition == ISRESTORED)
  475.                 wnd->RestoredRC = wnd->rc;
  476.             while (wnd1 != NULLWND)    {
  477.                 if (GetParent(wnd1) == wnd)
  478.                     SendMessage(wnd1, MOVE,
  479.                         wnd1->rc.lf+xdif, wnd1->rc.tp+ydif);
  480.                 wnd1 = NextWindow(wnd1);
  481.             }
  482.             if (wasVisible)
  483.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  484.             break;
  485.         }
  486.         case SIZE:    {
  487.             int wasVisible = isVisible(wnd);
  488.             WINDOW wnd1 = Focus.FirstWindow;
  489.             RECT rc;
  490.             int xdif = (int) p1 - wnd->rc.rt;
  491.             int ydif = (int) p2 - wnd->rc.bt;
  492.  
  493.             if (xdif == 0 && ydif == 0)
  494.                 return FALSE;
  495.             if (wasVisible)
  496.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  497.             wnd->rc.rt = (int) p1;
  498.             wnd->rc.bt = (int) p2;
  499.             wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  500.             wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  501.  
  502.             if (wnd->condition == ISRESTORED)
  503.                 wnd->RestoredRC = WindowRect(wnd);
  504.  
  505.             rc = ClientRect(wnd);
  506.             while (wnd1 != NULLWND)    {
  507.                 if (GetParent(wnd1) == wnd &&
  508.                         wnd1->condition == ISMAXIMIZED)
  509.                     SendMessage(wnd1, SIZE, RectRight(rc),
  510.                                             RectBottom(rc));
  511.                 wnd1 = NextWindow(wnd1);
  512.             }
  513.  
  514.             if (wasVisible)
  515.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  516.             break;
  517.         }
  518. #endif
  519.         case CLOSE_WINDOW:
  520.             wnd->condition = ISCLOSING;
  521.             if (wnd->PrevMouse != NULLWND)
  522.                 SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  523.             if (wnd->PrevKeyboard != NULLWND)
  524.                 SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  525.             /* ----------- hide this window ------------ */
  526.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  527.             /* --- close the children of this window --- */
  528.             while (!DoneClosing)    {
  529.                 WINDOW wnd1 = Focus.LastWindow;
  530.                 DoneClosing = TRUE;
  531.                 while (wnd1 != NULLWND)    {
  532.                     WINDOW prwnd = PrevWindow(wnd1);
  533.                     if (GetParent(wnd1) == wnd)    {
  534.                         if (inFocus == wnd1)    {
  535.                             RemoveFocusWindow(wnd);
  536.                             AppendFocusWindow(wnd);
  537.                             inFocus = wnd;
  538.                         }
  539.                         SendMessage(wnd1,CLOSE_WINDOW,0,0);
  540.                         DoneClosing = FALSE;
  541.                         break;
  542.                     }
  543.                     wnd1 = prwnd;
  544.                 }
  545.             }
  546.             /* --- change focus if this window had it -- */
  547.             SetPrevFocus(wnd);
  548.             /* ------- remove this window from the
  549.                     list of open windows ------------- */
  550.             RemoveBuiltWindow(wnd);
  551.             /* ------- remove this window from the
  552.                     list of in-focus windows ---------- */
  553.             RemoveFocusWindow(wnd);
  554.             /* -- free memory allocated to this window - */
  555.             if (wnd->title != NULL)
  556.                 free(wnd->title);
  557.             if (wnd->videosave != NULL)
  558.                 free(wnd->videosave);
  559.             free(wnd);
  560.             break;
  561.         default:
  562.             break;
  563.     }
  564.     return TRUE;
  565. }
  566. /* ---- compute lower left icon space in a rectangle ---- */
  567. #ifdef INCLUDE_SYSTEM_MENUS
  568. static RECT LowerLeft(RECT prc)
  569. {
  570.     RECT rc;
  571.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  572.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  573.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  574.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  575.     return rc;
  576. }
  577. /* ----- compute a position for a minimized window icon ---- */
  578. static RECT PositionIcon(WINDOW wnd)
  579. {
  580.     RECT rc;
  581.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  582.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  583.     RectRight(rc) = SCREENWIDTH-1;
  584.     RectBottom(rc) = SCREENHEIGHT-1;
  585.     if (GetParent(wnd))    {
  586.         WINDOW wnd1 = (WINDOW) -1;
  587.         RECT prc;
  588.         prc = WindowRect(GetParent(wnd));
  589.         rc = LowerLeft(prc);
  590.         /* - search for icon available location - */
  591.         while (wnd1 != NULLWND)    {
  592.             wnd1 = GetFirstChild(GetParent(wnd));
  593.             while (wnd1 != NULLWND)    {
  594.                 if (wnd1->condition == ISMINIMIZED)    {
  595.                     RECT rc1;
  596.                     rc1 = WindowRect(wnd1);
  597.                     if (RectLeft(rc1) == RectLeft(rc) &&
  598.                             RectTop(rc1) == RectTop(rc))    {
  599.                         RectLeft(rc) -= ICONWIDTH;
  600.                         RectRight(rc) -= ICONWIDTH;
  601.                         if (RectLeft(rc) < RectLeft(prc)+1)   {
  602.                             RectLeft(rc) =
  603.                                 RectRight(prc)-ICONWIDTH;
  604.                             RectRight(rc) =
  605.                                 RectLeft(rc)+ICONWIDTH-1;
  606.                             RectTop(rc) -= ICONHEIGHT;
  607.                             RectBottom(rc) -= ICONHEIGHT;
  608.                             if (RectTop(rc) < RectTop(prc)+1)
  609.                                 return LowerLeft(prc);
  610.                         }
  611.                         break;
  612.                     }
  613.                 }
  614.                 wnd1 = GetNextChild(GetParent(wnd), wnd1);
  615.             }
  616.         }
  617.     }
  618.     return rc;
  619. }
  620. /* ----- terminate the move or size operation ----- */
  621. static void TerminateMoveSize(void)
  622. {
  623.     px = py = -1;
  624.     diff = 0;
  625.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  626.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  627.     RestoreBorder(dwnd.rc);
  628.     WindowMoving = WindowSizing = FALSE;
  629. }
  630. /* ---- build a dummy window border for moving or sizing --- */
  631. static void near dragborder(WINDOW wnd, int x, int y)
  632. {
  633.     RestoreBorder(dwnd.rc);
  634.     /* ------- build the dummy window -------- */
  635.     dwnd.rc.lf = x;
  636.     dwnd.rc.tp = y;
  637.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  638.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  639.     dwnd.ht = WindowHeight(wnd);
  640.     dwnd.wd = WindowWidth(wnd);
  641.     dwnd.parent = GetParent(wnd);
  642.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  643.     InitWindowColors(&dwnd);
  644.     SaveBorder(dwnd.rc);
  645.     RepaintBorder(&dwnd, NULL);
  646. }
  647. /* ---- write the dummy window border for sizing ---- */
  648. static void near sizeborder(WINDOW wnd, int rt, int bt)
  649. {
  650.     int leftmost = GetLeft(wnd)+10;
  651.     int topmost = GetTop(wnd)+3;
  652.     int bottommost = SCREENHEIGHT-1;
  653.     int rightmost  = SCREENWIDTH-1;
  654.     if (GetParent(wnd))    {
  655.         bottommost = min(bottommost,
  656.             GetClientBottom(GetParent(wnd)));
  657.         rightmost  = min(rightmost,
  658.             GetClientRight(GetParent(wnd)));
  659.     }
  660.     rt = min(rt, rightmost);
  661.     bt = min(bt, bottommost);
  662.     rt = max(rt, leftmost);
  663.     bt = max(bt, topmost);
  664.     SendMessage(NULLWND, MOUSE_CURSOR, rt, bt);
  665.  
  666.     if (rt != px || bt != py)
  667.         RestoreBorder(dwnd.rc);
  668.  
  669.     /* ------- change the dummy window -------- */
  670.     dwnd.ht = bt-dwnd.rc.tp+1;
  671.     dwnd.wd = rt-dwnd.rc.lf+1;
  672.     dwnd.rc.rt = rt;
  673.     dwnd.rc.bt = bt;
  674.     if (rt != px || bt != py)    {
  675.         px = rt;
  676.         py = bt;
  677.         SaveBorder(dwnd.rc);
  678.         RepaintBorder(&dwnd, NULL);
  679.     }
  680. }
  681. #endif
  682. /* ----- adjust a rectangle to include the shadow ----- */
  683. #ifdef INCLUDE_SHADOWS
  684. static RECT adjShadow(WINDOW wnd)
  685. {
  686.     RECT rc;
  687.     rc = wnd->rc;
  688.     if (TestAttribute(wnd, SHADOW))    {
  689.         if (RectRight(rc) < SCREENWIDTH-1)
  690.             RectRight(rc)++;           
  691.         if (RectBottom(rc) < SCREENHEIGHT-1)
  692.             RectBottom(rc)++;
  693.     }
  694.     return rc;
  695. }
  696. #endif
  697. /* --- repaint a rectangular subsection of a window --- */
  698. #ifdef INCLUDE_MULTIDOCS
  699. static void near PaintOverLap(WINDOW wnd, RECT rc)
  700. {
  701.     int isBorder, isTitle, isData;
  702.     isBorder = isTitle = FALSE;
  703.     isData = TRUE;
  704.     if (TestAttribute(wnd, HASBORDER))    {
  705.         isBorder =  RectLeft(rc) == 0 &&
  706.                     RectTop(rc) < WindowHeight(wnd);
  707.         isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  708.                     RectRight(rc) >= WindowWidth(wnd)-1 &&
  709.                     RectTop(rc) < WindowHeight(wnd);
  710.         isBorder |= RectTop(rc) == 0 &&
  711.                     RectLeft(rc) < WindowWidth(wnd);
  712.         isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  713.                     RectBottom(rc) >= WindowHeight(wnd)-1 &&
  714.                     RectLeft(rc) < WindowWidth(wnd);
  715.     }
  716.     else if (TestAttribute(wnd, HASTITLEBAR))
  717.         isTitle = RectTop(rc) == 0 &&
  718.                   RectLeft(rc) > 0 &&
  719.                   RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  720.  
  721.     if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  722.         isData = FALSE;
  723.     if (RectTop(rc) >= WindowHeight(wnd)-BorderAdj(wnd))
  724.         isData = FALSE;
  725.     if (TestAttribute(wnd, HASBORDER))    {
  726.         if (RectRight(rc) == 0)
  727.             isData = FALSE;
  728.         if (RectBottom(rc) == 0)
  729.             isData = FALSE;
  730.     }
  731. #ifdef INCLUDE_SHADOWS
  732.     if (TestAttribute(wnd, SHADOW))
  733.         isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  734.                     RectBottom(rc) == WindowHeight(wnd);
  735. #endif
  736.     if (isData)
  737.         SendMessage(wnd, PAINT, (PARAM) &rc, 0);
  738.     if (isBorder)
  739.         SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  740.     else if (isTitle)
  741.         DisplayTitle(wnd, &rc);
  742. }
  743. /* ------ paint the part of a window that is overlapped
  744.             by another window that is being hidden ------- */
  745. static void PaintOver(WINDOW wnd)
  746. {
  747.         RECT wrc, rc;
  748. #ifdef INCLUDE_SHADOWS
  749.         wrc = adjShadow(HiddenWindow);
  750.         rc = adjShadow(wnd);
  751. #else
  752.         wrc = HiddenWindow->rc;
  753.         rc = wnd->rc;
  754. #endif
  755.         rc = subRectangle(rc, wrc);
  756.         if (ValidRect(rc))
  757.             PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  758. }
  759. /* --- paint the overlapped parts of all children --- */
  760. static void PaintOverChildren(WINDOW pwnd)
  761. {
  762.     WINDOW cwnd = GetFirstFocusChild(pwnd);
  763.     while (cwnd != NULLWND)    {
  764.         if (cwnd != HiddenWindow)    {
  765.             PaintOver(cwnd);
  766.             PaintOverChildren(cwnd);
  767.         }
  768.         cwnd = GetNextFocusChild(pwnd, cwnd);
  769.     }
  770. }
  771. /* -- recursive overlapping paint of parents -- */
  772. static void PaintOverParents(WINDOW wnd)
  773. {
  774.     WINDOW pwnd = GetParent(wnd);
  775.     if (pwnd != NULL)    {
  776.         PaintOverParents(pwnd);
  777.         PaintOver(pwnd);
  778.         PaintOverChildren(pwnd);
  779.     }
  780. }
  781. /* - paint the parts of all windows that a window is over - */
  782. static void near PaintOverLappers(WINDOW wnd)
  783. {
  784.     if (isVisible(wnd))    {
  785.         HiddenWindow = wnd;
  786.         PaintOverParents(wnd);
  787.     }
  788. }
  789. /* --- paint those parts of a window that are overlapped --- */
  790. static void near PaintUnder(WINDOW wnd)
  791. {
  792.     WINDOW hwnd = Focus.FirstWindow;
  793.     while (hwnd != NULLWND)    {
  794.         /* ---- don't bother testing self ----- */
  795.         if (hwnd != wnd)    {
  796.             /* --- see if other window is descendent --- */
  797.             WINDOW pwnd = GetParent(hwnd);
  798.             while (pwnd != NULLWND)    {
  799.                 if (pwnd == wnd)
  800.                     break;
  801.                 pwnd = GetParent(pwnd);
  802.             }
  803.             /* ----- don't test descendent overlaps ----- */
  804.             if (pwnd == NULLWND)    {
  805.                 /* -- see if other window is ancestor --- */
  806.                 pwnd = GetParent(wnd);
  807.                 while (pwnd != NULLWND)    {
  808.                     if (pwnd == hwnd)
  809.                         break;
  810.                     pwnd = GetParent(pwnd);
  811.                 }
  812.                 /* --- don't test ancestor overlaps --- */
  813.                 if (pwnd == NULLWND)    {
  814.                     /* ---- other window must be ahead in
  815.                         focus chain ----- */
  816.                     WINDOW fwnd = NextWindow(wnd);
  817.                     while (fwnd != NULLWND)    {
  818.                         if (fwnd == hwnd)
  819.                             break;
  820.                         fwnd = NextWindow(fwnd);
  821.                     }
  822.                     if (fwnd != NULLWND)    {
  823.                         HiddenWindow = hwnd;
  824.                         PaintOver(wnd);
  825.                     }
  826.                 }
  827.             }
  828.         }
  829.         hwnd = NextWindow(hwnd);
  830.     }
  831.     /* --------- repaint all children of this window
  832.         the same way ----------- */
  833.     hwnd = Focus.FirstWindow;
  834.     while (hwnd != NULLWND)    {
  835.         if (GetParent(hwnd) == wnd)
  836.             PaintUnder(hwnd);
  837.         hwnd = NextWindow(hwnd);
  838.     }
  839. }
  840. /* paint the parts of a window that are under other windows */
  841. static void near PaintUnderLappers(WINDOW wnd)
  842. {
  843.     WINDOW pwnd = wnd;
  844.     /* find oldest ancestor younger than application window */
  845.     while (pwnd != NULLWND && GetClass(pwnd) != APPLICATION) {
  846.         if (TestAttribute(wnd, SAVESELF))
  847.             break;
  848.         wnd = pwnd;
  849.         pwnd = GetParent(pwnd);
  850.     }
  851.     PaintUnder(wnd);
  852. }
  853. #endif
  854.  
  855. #ifdef INCLUDE_SYSTEM_MENUS
  856.  
  857. /* --- save video area to be used by dummy window border --- */
  858. static void SaveBorder(RECT rc)
  859. {
  860.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  861.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  862.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  863.         RECT lrc;
  864.         int i;
  865.         int *cp;
  866.  
  867.         lrc = rc;
  868.         RectBottom(lrc) = RectTop(lrc);
  869.         getvideo(lrc, Bsave);
  870.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  871.         getvideo(lrc, Bsave + Bwd);
  872.         cp = Bsave + Bwd * 2;
  873.         for (i = 1; i < Bht-1; i++)    {
  874.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  875.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  876.         }
  877.     }
  878. }
  879. /* ---- restore video area used by dummy window border ---- */
  880. static void RestoreBorder(RECT rc)
  881. {
  882.     if (Bsave != NULL)    {
  883.         RECT lrc;
  884.         int i;
  885.         int *cp;
  886.         lrc = rc;
  887.         RectBottom(lrc) = RectTop(lrc);
  888.         storevideo(lrc, Bsave);
  889.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  890.         storevideo(lrc, Bsave + Bwd);
  891.         cp = Bsave + Bwd * 2;
  892.         for (i = 1; i < Bht-1; i++)    {
  893.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  894.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  895.         }
  896.         free(Bsave);
  897.         Bsave = NULL;
  898.     }
  899. }
  900. #endif
  901. /* ----- test if screen coordinates are in a window ---- */
  902. static int InsideWindow(WINDOW wnd, int x, int y)
  903. {
  904.     RECT rc;
  905.     rc = WindowRect(wnd);
  906.     if (!TestAttribute(wnd, NOCLIP))    {
  907.         WINDOW pwnd = GetParent(wnd);
  908.         while (pwnd != NULL)    {
  909.             rc = subRectangle(rc, ClientRect(pwnd));
  910.             pwnd = GetParent(pwnd);
  911.         }
  912.     }
  913.     return InsideRect(x, y, rc);
  914. }
  915. /* ----- find window that screen coordinates are in --- */
  916. WINDOW inWindow(int x, int y)
  917. {
  918.     WINDOW wnd = Focus.LastWindow;
  919.     while (wnd != NULLWND)    {
  920.         if (SendMessage(wnd, INSIDE_WINDOW, x, y))    {
  921.             WINDOW wnd1 = GetLastChild(wnd);
  922.             while (wnd1 != NULLWND)    {
  923.                 if (SendMessage(wnd1, INSIDE_WINDOW, x, y)) {
  924.                     if (isVisible(wnd))  {
  925.                         wnd = wnd1;
  926.                         break;
  927.                     }
  928.                 }
  929.                 wnd1 = GetPrevChild(wnd, wnd1);
  930.             }
  931.             break;
  932.         }
  933.         wnd = PrevWindow(wnd);
  934.     }
  935.     return wnd;
  936. }
  937. /* ---- test window visible through chain of ancestors ---- */
  938. int isVisible(WINDOW wnd)
  939. {
  940.     while (wnd != NULLWND)    {
  941.         if (!isWndVisible(wnd))
  942.             return FALSE;
  943.         wnd = GetParent(wnd);
  944.     }
  945.     return TRUE;
  946. }
  947.